package com.lipaluma.field.mapper.single.impl;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.lipaluma.annotations.merge.OneToMany;
import com.lipaluma.context.Context;
import com.lipaluma.field.mapper.FieldMapper;
import com.lipaluma.field.mapper.mapping.Path;
import com.lipaluma.io.PathRow;
import com.lipaluma.io.Row;
import com.lipaluma.util.ReflectionUtils;
import com.lipaluma.xml.mapping.XmlFieldMapping;
import com.lipaluma.xml.mapping.XmlPathMapping;

public class PathOneToManyFieldMapper extends OneToManyFieldMapper {
	private Path mappingPath;
	
	public PathOneToManyFieldMapper() {
		super();
	}
	public PathOneToManyFieldMapper(FieldMapper fieldMapper) {
		super(fieldMapper);
	}	
	public PathOneToManyFieldMapper(FieldMapper fieldMapper, String path) {
		super(fieldMapper);
		this.mappingPath = new Path(path);
	}
	public PathOneToManyFieldMapper(FieldMapper fieldMapper, String path, boolean mandatoryPresence) {
		super(fieldMapper);
		this.mappingPath = new Path(path, mandatoryPresence);
	}
	
	@Override
	public void init(Context context, Field field) {
		super.init(context, field);
		if(mappingPath == null) {
			OneToMany annotation = field.getAnnotation(OneToMany.class);
			if(!annotation.path().isEmpty()) {
				mappingPath = new Path(annotation.path(), annotation.mandatoryPresence());
			} else
				mappingPath = new Path(field.getName(), annotation.mandatoryPresence());
		}
	}

	@Override
	public void init(Context context, Field field, XmlFieldMapping mapping) {
		super.init(context, field, mapping);
		XmlPathMapping xmlPath = (XmlPathMapping)mapping;
		if(StringUtils.isNotBlank(xmlPath.getPath()))
			mappingPath = new Path(xmlPath.getPath(), xmlPath.isPresenceMandatory());
		else 
			mappingPath = new Path(field.getName(), xmlPath.isPresenceMandatory());
	}
	
	@Override
	public Object unmarshal(Row row) {
		if(mappingPath == null)
			return super.unmarshal(row);
		PathRow pathRow = (PathRow) row;
		List<? extends PathRow> subRows = pathRow.extractSubRows(mappingPath);
		Collection<Object> collection = ReflectionUtils.instantiateCollection(getField().getType());
		for (PathRow subRow : subRows) {
			collection.add(getFieldMapper().unmarshal(subRow));
		}
		return collection;
	}
	
	public Path getMappingPath() {
		return mappingPath;
	}
}
